<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>连接监控仪表板</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.1/dist/chart.min.js"></script>
    <style>
        body {
            padding: 20px;
            background-color: #f8f9fa;
        }
        .card {
            margin-bottom: 20px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }
        .card-header {
            background-color: #6c757d;
            color: white;
            font-weight: bold;
        }
        .stat-card {
            text-align: center;
            padding: 15px;
        }
        .stat-value {
            font-size: 2rem;
            font-weight: bold;
            color: #0d6efd;
        }
        .stat-label {
            font-size: 0.9rem;
            color: #6c757d;
        }
        .chart-container {
            position: relative;
            height: 300px;
            width: 100%;
        }
        .event-list {
            max-height: 400px;
            overflow-y: auto;
        }
        .event-item {
            padding: 8px;
            border-bottom: 1px solid #dee2e6;
        }
        .event-item:last-child {
            border-bottom: none;
        }
        .event-time {
            font-size: 0.8rem;
            color: #6c757d;
        }
        .event-connected {
            color: #198754;
        }
        .event-disconnected {
            color: #dc3545;
        }
        .event-heartbeat-success {
            color: #0d6efd;
        }
        .event-heartbeat-failed {
            color: #fd7e14;
        }
        .refresh-btn {
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1 class="mb-4">连接监控仪表板</h1>
        
        <div class="d-flex justify-content-between align-items-center mb-4">
            <div>
                <button id="refreshBtn" class="btn btn-primary">刷新数据</button>
                <button id="resetStatsBtn" class="btn btn-warning ms-2">重置统计</button>
                <button id="triggerHeartbeatBtn" class="btn btn-info ms-2">触发心跳检测</button>
            </div>
            <div>
                <span id="lastUpdated" class="text-muted">最后更新: 未更新</span>
            </div>
        </div>
        
        <div class="row">
            <!-- 连接统计卡片 -->
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-value" id="totalConnections">0</div>
                    <div class="stat-label">总连接数</div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-value" id="activeConnections">0</div>
                    <div class="stat-label">活跃连接数</div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-value" id="connectionsCreated">0</div>
                    <div class="stat-label">已创建连接</div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-value" id="connectionsRemoved">0</div>
                    <div class="stat-label">已移除连接</div>
                </div>
            </div>
        </div>
        
        <div class="row mt-4">
            <!-- 心跳统计卡片 -->
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-value" id="heartbeatsSent">0</div>
                    <div class="stat-label">已发送心跳</div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-value" id="heartbeatsReceived">0</div>
                    <div class="stat-label">已接收心跳</div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-value" id="heartbeatsFailed">0</div>
                    <div class="stat-label">心跳失败</div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card stat-card">
                    <div class="stat-value" id="heartbeatSuccessRate">0%</div>
                    <div class="stat-label">心跳成功率</div>
                </div>
            </div>
        </div>
        
        <div class="row mt-4">
            <!-- 连接图表 -->
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header">连接趋势</div>
                    <div class="card-body">
                        <div class="chart-container">
                            <canvas id="connectionsChart"></canvas>
                        </div>
                    </div>
                </div>
            </div>
            
            <!-- 实例分布图表 -->
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header">实例连接分布</div>
                    <div class="card-body">
                        <div class="chart-container">
                            <canvas id="instancesChart"></canvas>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        
        <div class="row mt-4">
            <!-- 连接事件列表 -->
            <div class="col-md-12">
                <div class="card">
                    <div class="card-header">最近连接事件</div>
                    <div class="card-body">
                        <div class="event-list" id="eventsList">
                            <!-- 事件将通过JavaScript动态添加 -->
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <script>
        // 图表对象
        let connectionsChart;
        let instancesChart;
        
        // 连接数据历史
        const connectionHistory = {
            timestamps: [],
            totalConnections: [],
            activeConnections: []
        };
        
        // 初始化图表
        function initCharts() {
            // 连接趋势图表
            const connectionsCtx = document.getElementById('connectionsChart').getContext('2d');
            connectionsChart = new Chart(connectionsCtx, {
                type: 'line',
                data: {
                    labels: [],
                    datasets: [
                        {
                            label: '总连接数',
                            data: [],
                            borderColor: '#0d6efd',
                            backgroundColor: 'rgba(13, 110, 253, 0.1)',
                            tension: 0.4,
                            fill: true
                        },
                        {
                            label: '活跃连接数',
                            data: [],
                            borderColor: '#198754',
                            backgroundColor: 'rgba(25, 135, 84, 0.1)',
                            tension: 0.4,
                            fill: true
                        }
                    ]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    scales: {
                        y: {
                            beginAtZero: true
                        }
                    }
                }
            });
            
            // 实例分布图表
            const instancesCtx = document.getElementById('instancesChart').getContext('2d');
            instancesChart = new Chart(instancesCtx, {
                type: 'pie',
                data: {
                    labels: [],
                    datasets: [{
                        data: [],
                        backgroundColor: [
                            '#0d6efd',
                            '#198754',
                            '#dc3545',
                            '#fd7e14',
                            '#6f42c1',
                            '#20c997',
                            '#0dcaf0'
                        ]
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        legend: {
                            position: 'right'
                        }
                    }
                }
            });
        }
        
        // 更新统计卡片
        function updateStatCards(stats) {
            document.getElementById('totalConnections').textContent = stats.connectionStats.totalConnections || 0;
            document.getElementById('activeConnections').textContent = stats.connectionStats.activeConnections || 0;
            document.getElementById('connectionsCreated').textContent = stats.connectionStats.connectionsCreated || 0;
            document.getElementById('connectionsRemoved').textContent = stats.connectionStats.connectionsRemoved || 0;
            document.getElementById('heartbeatsSent').textContent = stats.connectionStats.heartbeatsSent || 0;
            document.getElementById('heartbeatsReceived').textContent = stats.connectionStats.heartbeatsReceived || 0;
            document.getElementById('heartbeatsFailed').textContent = stats.connectionStats.heartbeatsFailed || 0;
            
            const successRate = Math.round(stats.heartbeatSuccessRate * 100);
            document.getElementById('heartbeatSuccessRate').textContent = `${successRate}%`;
        }
        
        // 更新连接趋势图表
        function updateConnectionsChart(stats) {
            const timestamp = new Date(stats.timestamp);
            const timeString = timestamp.toLocaleTimeString();
            
            // 添加新数据点
            connectionHistory.timestamps.push(timeString);
            connectionHistory.totalConnections.push(stats.connectionStats.totalConnections || 0);
            connectionHistory.activeConnections.push(stats.connectionStats.activeConnections || 0);
            
            // 保持最多显示10个数据点
            if (connectionHistory.timestamps.length > 10) {
                connectionHistory.timestamps.shift();
                connectionHistory.totalConnections.shift();
                connectionHistory.activeConnections.shift();
            }
            
            // 更新图表数据
            connectionsChart.data.labels = connectionHistory.timestamps;
            connectionsChart.data.datasets[0].data = connectionHistory.totalConnections;
            connectionsChart.data.datasets[1].data = connectionHistory.activeConnections;
            connectionsChart.update();
        }
        
        // 更新实例分布图表
        function updateInstancesChart(stats) {
            const labels = [];
            const data = [];
            
            // 处理实例连接数据
            for (const [instanceId, count] of Object.entries(stats.instanceConnectionCounts)) {
                labels.push(instanceId);
                data.push(count);
            }
            
            // 更新图表数据
            instancesChart.data.labels = labels;
            instancesChart.data.datasets[0].data = data;
            instancesChart.update();
        }
        
        // 更新连接事件列表
        function updateEventsList(events) {
            const eventsList = document.getElementById('eventsList');
            eventsList.innerHTML = '';
            
            events.forEach(event => {
                const eventTime = new Date(event.timestamp).toLocaleString();
                let eventClass = '';
                
                switch (event.type) {
                    case 'CONNECTED':
                        eventClass = 'event-connected';
                        break;
                    case 'DISCONNECTED':
                        eventClass = 'event-disconnected';
                        break;
                    case 'HEARTBEAT_SUCCESS':
                        eventClass = 'event-heartbeat-success';
                        break;
                    case 'HEARTBEAT_FAILED':
                        eventClass = 'event-heartbeat-failed';
                        break;
                }
                
                const eventItem = document.createElement('div');
                eventItem.className = `event-item ${eventClass}`;
                eventItem.innerHTML = `
                    <div class="event-time">${eventTime}</div>
                    <div><strong>用户ID:</strong> ${event.userId} | <strong>实例:</strong> ${event.instanceId}</div>
                    <div><strong>事件:</strong> ${getEventTypeText(event.type)}</div>
                    ${event.details ? `<div><strong>详情:</strong> ${event.details}</div>` : ''}
                `;
                
                eventsList.appendChild(eventItem);
            });
        }
        
        // 获取事件类型文本
        function getEventTypeText(type) {
            switch (type) {
                case 'CONNECTED':
                    return '连接建立';
                case 'DISCONNECTED':
                    return '连接断开';
                case 'HEARTBEAT_SUCCESS':
                    return '心跳成功';
                case 'HEARTBEAT_FAILED':
                    return '心跳失败';
                default:
                    return type;
            }
        }
        
        // 加载统计数据
        function loadStatistics() {
            fetch('/api/v1/monitoring/statistics')
                .then(response => response.json())
                .then(result => {
                    if (result.code === 200 && result.data) {
                        const stats = result.data;
                        
                        // 更新统计卡片
                        updateStatCards(stats);
                        
                        // 更新图表
                        updateConnectionsChart(stats);
                        updateInstancesChart(stats);
                        
                        // 更新事件列表
                        updateEventsList(stats.recentEvents);
                        
                        // 更新最后更新时间
                        const lastUpdated = new Date().toLocaleString();
                        document.getElementById('lastUpdated').textContent = `最后更新: ${lastUpdated}`;
                    }
                })
                .catch(error => {
                    console.error('加载统计数据失败:', error);
                });
        }
        
        // 重置统计数据
        function resetStatistics() {
            fetch('/api/v1/monitoring/statistics/reset', {
                method: 'POST'
            })
                .then(response => response.json())
                .then(result => {
                    if (result.code === 200) {
                        alert('统计数据已重置');
                        loadStatistics();
                    }
                })
                .catch(error => {
                    console.error('重置统计数据失败:', error);
                });
        }
        
        // 触发心跳检测
        function triggerHeartbeatCheck() {
            fetch('/api/v1/monitoring/heartbeat/check', {
                method: 'POST'
            })
                .then(response => response.json())
                .then(result => {
                    if (result.code === 200) {
                        alert('心跳检测已触发');
                        // 延迟2秒后刷新数据，等待心跳检测完成
                        setTimeout(loadStatistics, 2000);
                    }
                })
                .catch(error => {
                    console.error('触发心跳检测失败:', error);
                });
        }
        
        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', function() {
            // 初始化图表
            initCharts();
            
            // 加载初始数据
            loadStatistics();
            
            // 设置定时刷新（每30秒）
            setInterval(loadStatistics, 30000);
            
            // 绑定按钮事件
            document.getElementById('refreshBtn').addEventListener('click', loadStatistics);
            document.getElementById('resetStatsBtn').addEventListener('click', resetStatistics);
            document.getElementById('triggerHeartbeatBtn').addEventListener('click', triggerHeartbeatCheck);
        });
    </script>
</body>
</html>